///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2007-2009 ILOG, S.A.
//  All Rights Reserved.
//  The following is ILOG Source Code.  No modifications may be made to the  
//  ILOG Source Code.  Any usage of the ILOG Source Code is subject to 
//  the terms and conditions of the ILOG End User License Agreement   
//  applicable to this ILOG software product.
//
///////////////////////////////////////////////////////////////////////////////

package ilog.gauges.rectangular.renderers
{
  import flash.display.DisplayObject;
  
  import ilog.gauges.gaugesClasses.rectangular.RectangularGaugeElement;
  import ilog.utils.CSSUtil;
  
  import mx.core.IDataRenderer;
  import mx.core.IFlexDisplayObject;
  import mx.core.UITextField;
  import mx.styles.CSSStyleDeclaration;

  /**
   * Horizontal alignment of the label relative to the element bounds.
   * Possible values are <code>"left"</code>, <code>"center"</code>,
   * and <code>"right"</code>.
   *
   * @default "center"
   */ 
  [Style(name="horizontalAlign", type="String", enumeration="left,center,right", inherit="no")]

  /**
   * Vertical alignment of the label relative to the element bounds.
   * Possible values are <code>"top"</code>, <code>"middle"</code>,
   * and <code>"bottom"</code>.
   *
   * @default "middle"
   */      
  [Style(name="verticalAlign", type="String", enumeration="top,middle,bottom", inherit="no")]

  [DefaultProperty("text")]

  /**
   * This class allows you to add a label to a rectangular gauge.
   * The position of the label in the renderer is controlled by 
   * <code>horizontalAlign</code> and <code>verticalAlign</code> style properties.
   * The font used to render the label is defined through the usual font
   * style properties available on the <code>GaugeElement</code> class.
   *  
   * @mxml
   *  
   * <p>The <code>&lt;ilog:RectangularLabelRenderer&gt;</code> tag inherits all the properties
   * of its parent classes and adds the following properties:</p>
   *  
   * <pre>
   * &lt;ilog:RectangularLabelRenderer
   *   <strong>Properties</strong>
   *   text=""
   *   labelRenderer="<i>UITextField</i>" 
   * 
   *   <strong>Styles</strong>
   *   horizontalAlign="center|left|right"
   *   verticalAlign="middle|top|bottom"
   * /&gt;
   * </pre>
   *
   * @includeExample examples/RectangularLabelRendererExample.mxml -noswf
   */  
  public class RectangularLabelRenderer extends RectangularGaugeElement
  {    
    private static var stylesInited:Boolean = initStyles(); 

    private static function initStyles():Boolean
    {
      var nStyle:CSSStyleDeclaration =
        CSSUtil.createSelector("RectangularLabelRenderer");   
            
      nStyle.defaultFactory = function():void  {
        this.horizontalAlign="center";
        this.verticalAlign="middle";
      }

      return true;
    }
    
    private var _label:UITextField;
    
    private var _textDirty:Boolean = false;

    private var _text:String;
    
    /**
     * Constructor.
     */
    public function RectangularLabelRenderer()
    {     
      super();
      _label = new UITextField();
      labelRenderer = _label;
    }
    
    [Inspectable(category="General")]
  
    /**
     * The plain text displayed by this control. 
     */    
    public function get text():String
    {
      return _text;
    }

    /**
     *  @private 
     */    
    public function set text(value:String):void
    {
      _text = value;
      _textDirty = true;
      invalidateProperties();
    }

    private var _labelRenderer:DisplayObject = null;
    
    [Inspectable(category="General")]
    
    /** 
     *  A reference to the display object used to render the label. 
     *  This property must implement the <code>IDataRenderer</code>
     *  and <code>IFlexDisplayObject</code> interfaces.
     *  If this property is <code>null</code>, a <code>UITextField</code> is used internally.
     *  The <code>data</code> property of the <code>labelRenderer</code> is assigned a String 
     *  object containing the text to be rendered.
     *
     *  @default null
     *  @since ILOG Elixir 2.0
     *  @ilog.reviewed SH 27 July 08
     */
    public function get labelRenderer():DisplayObject
    {
      if (_labelRenderer == _label)
        return null;
      else 
        return _labelRenderer;
    }

    /**
     *  @private
     */ 
    public function set labelRenderer(value:DisplayObject):void
    {
      if (_labelRenderer == value)
          return;

      if (_labelRenderer != null && contains(_labelRenderer))
        removeChild(_labelRenderer);
      
      
      if (value == null)
        _labelRenderer = _label;
      else
        _labelRenderer = value;
          
      addChild(_labelRenderer);
      invalidateProperties();
    }


    /**
     *  @private 
     */    
    override protected function commitProperties():void
    {
      super.commitProperties();
      if (_textDirty) {
        if (_labelRenderer != _label)
        {
          var idr:IDataRenderer = IDataRenderer(_labelRenderer);
          idr.data = text;
        }
        else
          _label.text = _text;

        _textDirty = false;
        invalidateSize();
        invalidateDisplayList();        
      }
    }

    /**
     * @private
     */
    override protected function measure():void
    {
      if (_labelRenderer != _label)
      {
        var ifd:IFlexDisplayObject = IFlexDisplayObject(_labelRenderer);
        measuredMinWidth = measuredWidth = ifd.measuredWidth;
        measuredMinHeight = measuredHeight = ifd.measuredHeight;
      }
      else
      {
        measuredMinWidth = _label.measuredMinWidth;
        measuredMinHeight = _label.measuredMinHeight;
        measuredWidth = _label.measuredWidth;
        measuredHeight = _label.measuredHeight;
      }      
    }    

    /**
     * Draws the label.
     * 
     * @param unscaledWidth Specifies the width, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleX</code> property of the component.
     *
     * @param unscaledHeight Specifies the height, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleY</code> property of the component. 
     */    
    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {                 
      var ifd:IFlexDisplayObject = IFlexDisplayObject(_labelRenderer);
      var tw:Number = Math.min(ifd.measuredWidth, unscaledWidth);
      var th:Number = ifd.measuredHeight;      
      var xOffset:Number = 0;
      var yOffset:Number = 0;
      var hAlign:String = getStyle("horizontalAlign");
      var vAlign:String = getStyle("verticalAlign");
                 
      if (hAlign == "center")
        xOffset = (unscaledWidth - tw) / 2;
      if (hAlign == "right")
        xOffset = unscaledWidth - tw;
      if (vAlign == "middle")
        yOffset = (unscaledHeight - th) / 2;
      if (vAlign == "bottom")
        yOffset = unscaledHeight - th;
      
      
      ifd.setActualSize(tw, th); 
      ifd.move(xOffset, yOffset);
    }   
  }  
}
